package cn.edu.sgu.www.mhxysy.service.chongwu.impl;

import cn.edu.sgu.www.mhxysy.consts.CustomMessages;
import cn.edu.sgu.www.mhxysy.dto.chongwu.ChongwuDTO;
import cn.edu.sgu.www.mhxysy.dto.zuoqi.ZuoqiChongwuDTO;
import cn.edu.sgu.www.mhxysy.entity.chongwu.*;
import cn.edu.sgu.www.mhxysy.entity.chongwu_equipment.ChongwuEquipment;
import cn.edu.sgu.www.mhxysy.entity.zuoqi.ZuoqiChongwu;
import cn.edu.sgu.www.mhxysy.enums.*;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.factory.impl.ChongwuAttributeFactory;
import cn.edu.sgu.www.mhxysy.factory.impl.ChongwuZizhiFactory;
import cn.edu.sgu.www.mhxysy.function.computer.score.impl.ChongwuScoreComputer;
import cn.edu.sgu.www.mhxysy.mapper.chongwu.*;
import cn.edu.sgu.www.mhxysy.mapper.chongwu_equipment.ChongwuEquipmentMapper;
import cn.edu.sgu.www.mhxysy.mapper.zuoqi.ZuoqiChongwuMapper;
import cn.edu.sgu.www.mhxysy.pager.Pager;
import cn.edu.sgu.www.mhxysy.pager.chongwu.ChongwuPager;
import cn.edu.sgu.www.mhxysy.redis.repository.impl.ChongwuRepository;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.chongwu.ChongwuService;
import cn.edu.sgu.www.mhxysy.util.ObjectUtils;
import cn.edu.sgu.www.mhxysy.util.StringUtils;
import cn.edu.sgu.www.mhxysy.vo.chongwu.ChongwuVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Slf4j
@Service
public class ChongwuServiceImpl implements ChongwuService {

	private final ChongwuMapper chongwuMapper;
	private final ChongwuRepository chongwuRepository;
	private final ChongwuSkillMapper chongwuSkillMapper;
	private final ChongwuZizhiMapper chongwuZizhiMapper;
	private final ZuoqiChongwuMapper zuoqiChongwuMapper;
	private final ChongwuNeidanMapper chongwuNeidanMapper;
	private final ChongwuJiadianMapper chongwuJiadianMapper;
	private final ChongwuScoreComputer chongwuScoreComputer;
	private final ChongwuAttributeMapper chongwuAttributeMapper;
	private final ChongwuEquipmentMapper chongwuEquipmentMapper;
	private final ChongwuNeidanResonanceMapper chongwuNeidanResonanceMapper;

	@Autowired
	public ChongwuServiceImpl(
			ChongwuMapper chongwuMapper,
			ChongwuRepository chongwuRepository,
			ChongwuSkillMapper chongwuSkillMapper,
			ChongwuZizhiMapper chongwuZizhiMapper,
			ZuoqiChongwuMapper zuoqiChongwuMapper,
			ChongwuNeidanMapper chongwuNeidanMapper,
			ChongwuJiadianMapper chongwuJiadianMapper,
			ChongwuScoreComputer chongwuScoreComputer,
			ChongwuAttributeMapper chongwuAttributeMapper,
			ChongwuEquipmentMapper chongwuEquipmentMapper,
			ChongwuNeidanResonanceMapper chongwuNeidanResonanceMapper) {
		this.chongwuMapper = chongwuMapper;
		this.chongwuRepository = chongwuRepository;
		this.chongwuSkillMapper = chongwuSkillMapper;
		this.chongwuZizhiMapper = chongwuZizhiMapper;
		this.zuoqiChongwuMapper = zuoqiChongwuMapper;
		this.chongwuNeidanMapper = chongwuNeidanMapper;
		this.chongwuJiadianMapper = chongwuJiadianMapper;
		this.chongwuScoreComputer = chongwuScoreComputer;
		this.chongwuAttributeMapper = chongwuAttributeMapper;
		this.chongwuEquipmentMapper = chongwuEquipmentMapper;
		this.chongwuNeidanResonanceMapper = chongwuNeidanResonanceMapper;
	}

	@Override
	public Integer compute(String chongwuId) {
		Integer score = chongwuScoreComputer.compute(chongwuId);

		// update chongwu set score = #{score} where id = #{chongwuId}
		UpdateWrapper<Chongwu> updateWrapper = new UpdateWrapper<>();

		updateWrapper.set("score", score);
		updateWrapper.eq("id", chongwuId);

		int update = chongwuMapper.update(updateWrapper.getEntity(), updateWrapper);

		if (update == 1) {
			return score;
		}

		throw new GlobalException(ResponseCode.BAD_REQUEST, CustomMessages.OPERATE_FAILURE);
	}

	@Override
	public void change(ZuoqiChongwuDTO zuoqiChongwuDTO) {
		String chongwuId = zuoqiChongwuDTO.getChongwuId();
		Integer tongyuStatus = zuoqiChongwuDTO.getTongyuStatus();

		Chongwu chongwu = chongwuMapper.selectById(chongwuId);

		if (!tongyuStatus.equals(chongwu.getTongyuStatus())) {
			throw new GlobalException(ResponseCode.CONFLICT, "宠物的统御状态已经更新，请刷新页面后重新操作！");
		}

		if (TongyuStatus.WTY.getValue().equals(tongyuStatus)) {
			throw new GlobalException(ResponseCode.CONFLICT, "宠物状态为未统御，不允许更换统御操作！");
		}

		// 删除缓存（延时双删）
		String zuoqiId = zuoqiChongwuDTO.getZuoqiId();
		Integer location = zuoqiChongwuDTO.getLocation();

		chongwuRepository.delayDoubleDelete(chongwuId, new Consumer<String>() {
			@Override
			public void accept(String chongwuId) {
				UpdateWrapper<ZuoqiChongwu> updateWrapper = new UpdateWrapper<>();

				updateWrapper.set("zuoqi_id", zuoqiId);

				updateWrapper.eq("location", location);
				updateWrapper.eq("chongwu_id", chongwuId);

				int update = zuoqiChongwuMapper.update(updateWrapper.getEntity(), updateWrapper);

				if (update < 1) {
					throw new GlobalException(ResponseCode.SERVER_ERROR, "数据更新失败，请刷新页面后重试。");
				}
			}
		});
	}

	@Override
	public void tongyu(ZuoqiChongwuDTO zuoqiChongwuDTO) {
		String zuoqiId = zuoqiChongwuDTO.getZuoqiId();
		Integer location = zuoqiChongwuDTO.getLocation();
		String chongwuId = zuoqiChongwuDTO.getChongwuId();
		Integer tongyuStatus = zuoqiChongwuDTO.getTongyuStatus();

		Chongwu chongwu = chongwuMapper.selectById(chongwuId);

		if (!tongyuStatus.equals(chongwu.getTongyuStatus())) {
			throw new GlobalException(ResponseCode.CONFLICT, "宠物的统御状态已经更新，请刷新页面后重新操作！");
		}

		// 统御状态为[0-未统御]，则操作为【统御】
		if (TongyuStatus.WTY.getValue().equals(tongyuStatus)) {
			// 获取坐骑统御的宠物总数
			QueryWrapper<ZuoqiChongwu> queryWrapper = new QueryWrapper<>();

			queryWrapper.eq("zuoqi_id", zuoqiId);

			long count =  zuoqiChongwuMapper.selectCount(queryWrapper);

			// 已经统御两只宠物，终止操作，抛出异常
			if (count >= 2) {
				throw new GlobalException(ResponseCode.CONFLICT, "该坐骑已经统御了两只宠物！");
			}

			// 同一位置不允许重复统御宠物
			queryWrapper.eq("location", location);

			count = zuoqiChongwuMapper.selectCount(queryWrapper);

			if (count > 0) {
				throw new GlobalException(ResponseCode.CONFLICT, "该位置已经统御了宠物！");
			}

			// 修改宠物的统御状态为：1-已统御
			UpdateWrapper<Chongwu> updateWrapper = new UpdateWrapper<>();

			updateWrapper.eq("id", chongwuId);
			updateWrapper.eq("tongyu_status", TongyuStatus.WTY.getValue());

			updateWrapper.set("tongyu_status", TongyuStatus.YTY.getValue());

			int update = chongwuMapper.update(updateWrapper.getEntity(), updateWrapper);

			if (update < 1) {
				throw new GlobalException(ResponseCode.SERVER_ERROR, "数据更新失败，请刷新页面后重试。");
			}

			// 添加坐骑宠物
			ZuoqiChongwu zuoqiChongwu = new ZuoqiChongwu();

			zuoqiChongwu.setId(null);
			zuoqiChongwu.setZuoqiId(zuoqiId);
			zuoqiChongwu.setLocation(location);
			zuoqiChongwu.setChongwuId(chongwuId);

			zuoqiChongwuMapper.insert(zuoqiChongwu);
		} else { // 统御状态为[1-统御中]，则操作为[取消统御]
			// 修改宠物的统御状态为：0-未统御
			UpdateWrapper<Chongwu> updateWrapper = new UpdateWrapper<>();

			updateWrapper.eq("id", chongwuId);
			updateWrapper.eq("tongyu_status", TongyuStatus.YTY.getValue());

			updateWrapper.set("tongyu_status", TongyuStatus.WTY.getValue());

			int update = chongwuMapper.update(updateWrapper.getEntity(), updateWrapper);

			if (update < 1) {
				throw new GlobalException(ResponseCode.SERVER_ERROR, "数据更新失败，请刷新页面后重试。");
			}

			// 删除坐骑宠物
			QueryWrapper<ZuoqiChongwu> queryWrapper = new QueryWrapper<>();

			queryWrapper.eq("chongwu_id", chongwuId);
			queryWrapper.eq("location", location);

			zuoqiChongwuMapper.delete(queryWrapper);
		}

		// 删除缓存
		chongwuRepository.deleteList();
		chongwuRepository.deleteById(chongwuId);
	}

	@Override
	public void insert(ChongwuDTO chongwuDTO) {
		Chongwu chongwu = toEntity(chongwuDTO);
		String chongwuId = chongwu.uuid();

		/*
		 * 1、添加宠物资质
		 */
		ChongwuZizhiFactory chongwuZizhiFactory = new ChongwuZizhiFactory();
		ChongwuZizhi chongwuZizhi = chongwuZizhiFactory.produce();

		chongwuZizhi.setChongwuId(chongwuId);

		chongwuZizhiMapper.insert(chongwuZizhi);

		/*
		 * 2、添加宠物
		 */
		chongwu.setId(chongwuId);
		chongwu.setTongyuStatus(TongyuStatus.WTY.getValue());

		chongwuMapper.insert(chongwu);

		/*
		 * 3、添加宠物加点
		 */
		ChongwuJiadian chongwuJiadian = new ChongwuJiadian();

		Integer grade = chongwu.getGrade();
		String jiadianId = chongwuJiadian.uuid();

		chongwuJiadian.setId(jiadianId);
		chongwuJiadian.setMoli(grade + 10);
		chongwuJiadian.setTizhi(grade + 10);
		chongwuJiadian.setNaili(grade + 10);
		chongwuJiadian.setMinjie(grade + 10);
		chongwuJiadian.setLiliang(grade + 10);
		chongwuJiadian.setChongwuId(chongwu.getId());
		chongwuJiadian.setOpenStatus(OpenStatus.OPEN.getValue());
		chongwuJiadian.setUnlockStatus(UnlockStatus.YJS.getValue());
		chongwuJiadian.setJiadianSchema(JiadianSchemas.JDFAY.getValue());

		chongwuJiadianMapper.insert(chongwuJiadian);

		/*
		 * 4、添加宠物属性
		 */
		ChongwuAttributeFactory chongwuAttributeFactory = new ChongwuAttributeFactory();
		ChongwuAttribute chongwuAttribute = chongwuAttributeFactory.produce();

		int dkfy = (chongwuDTO.getGrade() - 10) * 20; // 抵抗封印

		chongwuAttribute.setDkfy(dkfy > 0 ? dkfy: 1);
		chongwuAttribute.setChongwuId(chongwuId);
		chongwuAttribute.setJiadianId(jiadianId);

		chongwuAttributeMapper.insert(chongwuAttribute);

		// 删除宠物列表缓存
		chongwuRepository.deleteList();
	}

	@Override
	public void deleteById(String chongwuId) {
		Chongwu chongwu = chongwuMapper.selectById(chongwuId);

		// 判断宠物不存在，抛出异常
		if (chongwu == null) {
			throw new GlobalException(ResponseCode.NOT_FOUND, "删除失败，宠物不存在~");
		}

		/*
		 * 1、恢复宠物装备的状态
		 */
		UpdateWrapper<ChongwuEquipment> updateWrapper = new UpdateWrapper<>();

		updateWrapper.eq("chongwu_id", chongwuId);

		updateWrapper.set("chongwu_id", null);
		updateWrapper.set("wear_status", WearStatus.WCD.getValue());

		chongwuEquipmentMapper.update(updateWrapper.getEntity(), updateWrapper);

		// 2、删除宠物资质
		Map<String, Object> columnMap = new HashMap<>();

		columnMap.put("chongwu_id", chongwuId);

		chongwuZizhiMapper.deleteByMap(columnMap);

		/*
		 * 3、删除宠物加点、属性
		 */
		// 3.1 删除宠物属性
		chongwuAttributeMapper.deleteByMap(columnMap);

		// 3.2 删除宠物加点
		chongwuJiadianMapper.deleteByMap(columnMap);


		// 4、删除宠物内丹
		// 4.1 删除内丹共鸣
		QueryWrapper<ChongwuNeidanResonance> queryWrapper = new QueryWrapper<>();

		queryWrapper.in("neidan_id",
				"select neidan_id from chongwu_neidan where chongwu_id = " + chongwuId);

		chongwuNeidanResonanceMapper.delete(queryWrapper);

		// 4.2 删除内丹
		chongwuNeidanMapper.deleteByMap(columnMap);

		// 5、删除宠物技能
		chongwuSkillMapper.deleteByMap(columnMap);

		// 6、删除宠物
		chongwuMapper.deleteById(chongwuId);

		// 删除宠物缓存
		chongwuRepository.deleteById(chongwuId);
		chongwuRepository.deleteList();
	}

	@Override
	public void updateById(ChongwuDTO chongwuDTO) {
		ObjectUtils.requireNonNull(chongwuDTO.getId(), CustomMessages.ID_NOT_NULL);

		Chongwu chongwu = toEntity(chongwuDTO);

		chongwuMapper.updateById(chongwu);

		// 删除宠物缓存
		chongwuRepository.deleteById(chongwuDTO.getId());
		chongwuRepository.deleteList();
	}

	@Override
	public List<Chongwu> selectAll() {
		return chongwuRepository.selectList();
	}

	@Override
	public Chongwu selectById(String id) {
		return chongwuRepository.selectById(id);
	}

	@Override
	public List<Chongwu> selectByRoleId(String roleId) {
		QueryWrapper<Chongwu> queryWrapper = new QueryWrapper<>();

		queryWrapper.eq(
				StringUtils.isEmpty(roleId),
				"role_id", roleId
		);

		return chongwuMapper.selectList(queryWrapper);
	}

	@Override
	public Page<Chongwu> selectByPage(ChongwuPager pager) {
		List<Integer> skillIds = pager.getSkillIds();

		pager.setTotal(skillIds != null ? skillIds.size() : 0);
		pager.setStatement(Pager.getStatement(pager));

		Page<Chongwu> page = Pager.ofPage(pager);

		return chongwuMapper.selectByPage(page, pager);
	}

	@Override
	public List<ChongwuVO> selectByZuoqiId(String zuoqiId) {
		return chongwuMapper.selectByZuoqiId(zuoqiId);
	}

	private Chongwu toEntity(ChongwuDTO chongwuDTO) {
		Chongwu chongwu = new Chongwu();

		chongwu.setId(chongwuDTO.getId());
		chongwu.setName(chongwuDTO.getName());
		chongwu.setScore(chongwuDTO.getScore());
		chongwu.setGrade(chongwuDTO.getGrade());
		chongwu.setRoleId(chongwuDTO.getRoleId());
		chongwu.setLifespan(chongwuDTO.getLifespan());
		chongwu.setZizhiType(chongwuDTO.getZizhiType());
		chongwu.setCategoryId(chongwuDTO.getCategoryId());

		return chongwu;
	}

}